package com.example.work.operator;

import com.ql.util.express.Operator;
import com.ql.util.express.exception.QLException;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * anyIn操作符实现
 *
 * 1,2,3 anyIn (3,4,5) 返回true
 * 1,2,3 anyIn [3,4,5] 返回true
 *
 * list.add(1);
 * list.add(2);
 * list.add(3);
 * list anyIn [3,4,5] 返回true
 *
 */
public class AnyInOperator extends Operator {
    @Override
    public Object executeInner(Object[] objects) throws Exception {
        int length=2;
        if (objects.length != length || Objects.isNull(objects[0]) || Objects.isNull(objects[1])){
            throw new QLException("参数不合法");
        }

        String msg;
        if (!(objects[0] instanceof String) && !(objects[0] instanceof List)){
            msg = "对象类型不匹配，只有字符串、List类型才才能执行 anyIn 操作,当前数据类型是:";
            throw new QLException(msg + objects[0].getClass().getName());
        }
        if (!objects[1].getClass().isArray() && !(objects[1] instanceof List) && !(objects[1] instanceof String)){
            msg = "目标对象类型不匹配，只有数组、List、String类型才才能执行 anyIn 操作,当前数据类型是:";
            throw new QLException(msg + objects[1].getClass().getName());
        }

        List<String> left = null;
        if (objects[0] instanceof String){
            left = Arrays.asList(((String) objects[0]).split(","));
        }else if (objects[0] instanceof List){
            left = ((List<?>) objects[0]).stream().map(x -> String.valueOf(x)).collect(Collectors.toList());
        }

        //判断左右两个列表是否有交集
        if (objects[1].getClass().isArray()){
            int len = Array.getLength(objects[1]);
            for(int i = 0; i < len; ++i) {
                String value = String.valueOf(Array.get(objects[1], i));
                if(left.stream().filter(l -> l.equals(value)).findFirst().isPresent()){
                    return Boolean.TRUE;
                }
            }
            return Boolean.FALSE;
        }else if(objects[1] instanceof List){
            List<String> finalLeft = left;
            return ((List<?>) objects[1]).stream().filter(r -> finalLeft.contains(String.valueOf(r)))
                    .findFirst().isPresent();
        }else if (objects[1] instanceof String){
            List<String> finalLeft1 = left;
            return Arrays.asList(((String) objects[1]).split(","))
                    .stream().filter(x -> finalLeft1.contains(x)).findFirst().isPresent();
        }
        return Boolean.FALSE;
    }
}
